package com.djl.entity;

import com.djl.util.Function;

import javax.persistence.Entity;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class Criteria {
    //缓存属性
    private static final Map<String, String> PROPERTY_FUNC_CACHE = new ConcurrentHashMap();

    public Map<String,Object> paramMap = new ConcurrentHashMap<String,Object>();

    private String key;

    private Object value;

    public String table;


    public Criteria(String key,String table){
        this.key = key;
        this.table=table;
    }

    public static <T,R> Criteria where(Function<T,R> function){
        String key = "";
        String table = "";
        Class<? extends Function> clazz = function.getClass();
        try{
            Method method = function.getClass().getDeclaredMethod("writeReplace");
            method.setAccessible(Boolean.TRUE);
            SerializedLambda serializedLambda = (SerializedLambda)method.invoke(function);
            table = Class.forName(serializedLambda.getImplClass().replaceAll("\\/","\\.")).getAnnotation(Entity.class).name();
            String getter = serializedLambda.getImplMethodName();
            key = resolveFieldName(getter);
        }catch (Exception e){
            e.printStackTrace();
        }
        return new Criteria(key,table);
    }

    public Criteria is(Object value){
        this.value = value;
        paramMap.put(key,"'"+value+"'");
        return this;
    }

    public <T,R>Criteria and(Function<T,R> function){
        this.key= null;
        this.value = null;
        return getParams(function);
    }


    private static String resolveFieldName(String getMethodName) {
        if (getMethodName.startsWith("get")) {
            getMethodName = getMethodName.substring(3);
        } else if (getMethodName.startsWith("is")) {
            getMethodName = getMethodName.substring(2);
        }

        return firstToLowerCase(getMethodName);
    }

    private static String firstToLowerCase(String param) {
        return org.apache.commons.lang.StringUtils.isBlank(param) ? "" : param.substring(0, 1).toLowerCase() + param.substring(1);
    }


    public <T,R>Criteria getParams(Function<T,R> function){
        Class<? extends Function> clazz = function.getClass();
        try{
            Method method = function.getClass().getDeclaredMethod("writeReplace");
            method.setAccessible(Boolean.TRUE);
            SerializedLambda serializedLambda = (SerializedLambda)method.invoke(function);
            String getter = serializedLambda.getImplMethodName();
            key = resolveFieldName(getter);
        }catch (Exception e){
            e.printStackTrace();
        }
        return this;
    }


}
